using System;
using System.Collections.Generic;
using System.Text;
using IGGCore;

namespace IGGConsole
{
    /// <summary>
    /// The boxes manager for console games display
    /// </summary>
    public class BoxesManager
    {
        private List<Game> m_boxedGames;
        private int m_maxByRow = TxtConstants.BOXES_INITIAL_MAXROW;
        private int m_rows;
        private int m_lastRowBoxes;
        private int m_currentSelectionIndex = -1;

        /// <summary>
        /// Constructor
        /// </summary>
        public BoxesManager()
        {
            m_boxedGames = new List<Game>();
        }

        /// <summary>
        /// Initialize the boxed games list
        /// </summary>
        public void InitializeBoxedGames(Scoreboard scoreboard)
        {
            m_boxedGames.Clear();
            AddGamesToBoxedGames(scoreboard.GamesList);
        }

        /// <summary>
        /// Add the games contained in the specified list to the boxed games
        /// </summary>
        private void AddGamesToBoxedGames(GameList list)
        {
            foreach (Game game in list.Games)
            {
                m_boxedGames.Add(game);
            }
        }

        /// <summary>
        /// Build the games boxes
        /// </summary>
        public void BuildBoxes(Scoreboard scoreboard)
        {
            int gameIndex = 0;
            int allgamesCount = scoreboard.GamesList.Games.Count;
            if (allgamesCount == 0)
            {
                Console.WriteLine("");
                if (ToolBox.YesterdayScores())
                {
                    Console.WriteLine(" No games were played yesterday.");
                }
                else
                {
                    Console.WriteLine(" No games scheduled.");
                }
                return;
            }
            m_rows = 1;
            m_lastRowBoxes = 0;
            if (allgamesCount < m_maxByRow)
            {
                m_maxByRow = allgamesCount;
            }
            else
            {
                m_rows = (int)(Math.Ceiling(((float)allgamesCount) / (float)m_maxByRow));
                m_lastRowBoxes = allgamesCount % m_maxByRow;
                if (m_lastRowBoxes == 0)
                {
                    m_lastRowBoxes = m_maxByRow;
                }
            }
            WriteBoxesRow(gameIndex, scoreboard.SelectedGame.Id, m_maxByRow);
            gameIndex += m_maxByRow;
            if (m_rows > 1)
            {
                int numColumns = m_maxByRow;
                if (m_rows == 2)
                {
                    numColumns = m_lastRowBoxes;
                }
                WriteBoxesRow(gameIndex, scoreboard.SelectedGame.Id, numColumns);
                gameIndex += numColumns;
            }
            if (m_rows > 2)
            {
                int numColumns = m_maxByRow;
                if (m_rows == 3)
                {
                    numColumns = m_lastRowBoxes;
                }
                WriteBoxesRow(gameIndex, scoreboard.SelectedGame.Id, numColumns);
                gameIndex += numColumns;
            }
            if (m_rows > 3)
            {
                WriteBoxesRow(gameIndex, scoreboard.SelectedGame.Id, m_lastRowBoxes);
            }
        }

        /// <summary>
        /// Write a row of game boxes
        /// </summary>
        /// <param name="gameIndex"></param>
        /// <param name="selectedId"></param>
        /// <param name="numrow"></param>
        private void WriteBoxesRow(int gameIndex, string selectedId, int numcolumn)
        {
            StringFormatter.WriteGraphicBoxStructure(true, numcolumn);
            WriteBoxContent(gameIndex, numcolumn, selectedId, true);
            WriteBoxContent(gameIndex, numcolumn, selectedId, false);
            StringFormatter.WriteGraphicBoxStructure(false, numcolumn);
        }

        /// <summary>
        /// Write the box content
        /// </summary>
        private void WriteBoxContent(int start, int num, string selectedId, bool firstLine)
        {
            for (int i = start; i < start + num; i++)
            {
                if (m_boxedGames[i].Id == selectedId)
                {
                    WriteBoxContentLine(m_boxedGames[i], true, firstLine);
                    m_currentSelectionIndex = i;
                }
                else
                {
                    WriteBoxContentLine(m_boxedGames[i], false, firstLine);
                }
            }

            Console.WriteLine();
        }

        /// <summary>
        /// Write the box content line
        /// </summary>
        private void WriteBoxContentLine(Game game, bool selected, bool firstLine)
        {
            Console.Write((char)179);
            if (selected)
            {
                Console.ForegroundColor = TxtConstants.COMMANDLINE_HIGHLIGHT;
            }
            string line1 = "      ";
            string line2 = "      ";
            switch (game.Status.Indicator.Category)
            {
                case Indicator.IndicatorCategoy.TERMINATED:
                    line1 = " "
                        + ToolBox.GetFormattedStringPadRight(game.Linescore.GetAwayLineScore().Runs.ToString(), 2)
                        + " F ";
                    line2 = " " + ToolBox.GetFormattedStringPadRight(game.Linescore.GetHomeLineScore().Runs.ToString(), 5);
                    break;
                case Indicator.IndicatorCategoy.INTERRUPTED:
                    line1 = "    R ";
                    break;
                case Indicator.IndicatorCategoy.IN_PROGRESS:
                    string stat = "BOT";
                    if (game.Status.InningTop)
                    {
                        stat = "TOP";
                    }
                    line1 = " " + ToolBox.GetFormattedStringPadRight(game.Linescore.GetAwayLineScore().Runs.ToString(), 2)
                        + stat;
                    line2 = " " + ToolBox.GetFormattedStringPadRight(game.Linescore.GetHomeLineScore().Runs.ToString(), 2)
                        + " " + ToolBox.GetFormattedStringPadRight(game.Status.Inning.ToString(), 2);
                    break;
                case Indicator.IndicatorCategoy.NEXT:
                    line1 = " " + ToolBox.GetFormattedStringPadRight(game.StartTime, 5);
                    break;
                case Indicator.IndicatorCategoy.WARMUP:
                    line1 = " " + ToolBox.GetFormattedStringPadRight(game.StartTime, 5);
                    break;
            }
            if (firstLine)
            {
                Console.Write(ToolBox.GetFormattedStringPadRight(game.AwayTeam.Abbrv.ToUpper(), 3) + " " + line1);
            }
            else
            {
                Console.Write(ToolBox.GetFormattedStringPadRight(game.HomeTeam.Abbrv.ToUpper(), 3) + " " + line2);
            }
            Console.ForegroundColor = ConsoleColor.Gray;
            Console.Write((char)179);
        }

        /// <summary>
        /// Manage arrow navigation on the selection
        /// </summary>
        public void ManageSelectionNavigator(Scoreboard scoreboard, ConsoleKey arrowKey)
        {
            int allgamesCount = scoreboard.GamesList.Games.Count;
            switch (arrowKey)
            {
                case ConsoleKey.UpArrow:
                    if (m_currentSelectionIndex >= m_maxByRow)
                    {
                        scoreboard.SelectedGame = m_boxedGames[m_currentSelectionIndex - m_maxByRow];
                    }
                    break;
                case ConsoleKey.DownArrow:
                    if ((m_currentSelectionIndex + m_maxByRow) < allgamesCount)
                    {
                        scoreboard.SelectedGame = m_boxedGames[m_currentSelectionIndex + m_maxByRow];
                    }
                    break;
                case ConsoleKey.LeftArrow:
                    if (m_currentSelectionIndex > 0)
                    {
                        scoreboard.SelectedGame = m_boxedGames[m_currentSelectionIndex - 1];
                    }
                    break;
                case ConsoleKey.RightArrow:
                    if (m_currentSelectionIndex < (allgamesCount - 1))
                    {
                        scoreboard.SelectedGame = m_boxedGames[m_currentSelectionIndex + 1];
                    }
                    break;
            }
        }
    }
}
